シリアルなCPUプログラミングからGPUプログラミングへ移行するには、パラダイムの転換が必要です。要素単位の反復処理から ブロックベースの実行へと変える必要があります。データをスカラのストリームとしてではなく、ハードウェア帯域幅を飽和させるようにスケジュールされた「ブロック」の集合として捉えるようになります。
1. メモリバウンド対計算バウンド
カーネルのボトルネックは、数学演算とメモリアクセスの比率によって決まります。 ベクトル加算はしばしばメモリバウンド なぜなら、3回のメモリ操作(2回のロード、1回のストア)に対して1回の加算しか行わないためです。ハードウェアはDRAMからの待ち時間に費やす時間が、計算時間よりも長くなります。
2. BLOCK_SIZEの役割
BLOCK_SIZE は並列処理の粒度を定義します。もし小さすぎると、GPUの広い実行レーンを十分に活用できず、効率が低下します。最適なサイズは、メモリバスを飽和させるのに十分な「進行中の作業」を確保します。
3. 並列度(オキュパンシー)による遅延隠蔽
オキュパンシー はGPU上のアクティブなブロック数を表します。最終的な目的ではありませんが、他のブロックがVRAMからの高遅延メモリフェッチを待っている間に、スケジューラが新しいブロックを投入して計算を実行できるようにします。
4. ハードウェアの活用
性能を最大化するためには、私たちの BLOCK_SIZE をGPUアーキテクチャのメモリコアレスリングルールに合わせる必要があります。これにより、連続するスレッドが連続するメモリアドレスにアクセスすることを保証します。
TERMINALbash — 80x24
> Ready. Click "Run" to execute.
>